Skip to content

Commit 86ab7f1

Browse files
authored
Merge pull request #25 from silnrsi/feature-cmake-fetchcontent
Replace the custom NuGet wrangling with the more flexible, and cross-platform, FetchContent module, for grabbing the ICU dependency.
2 parents 99d7485 + 850a627 commit 86ab7f1

File tree

5 files changed

+101
-114
lines changed

5 files changed

+101
-114
lines changed

CMakeLists.txt

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
cmake_minimum_required(VERSION 3.11)
2-
include(TestBigEndian)
3-
include(GNUInstallDirs)
42
project(grcompiler)
3+
enable_language(CXX C)
4+
enable_testing()
5+
6+
include(TestBigEndian)
7+
include(FetchContent)
58
include(CTest)
69

7-
enable_language(CXX C)
810
set(CMAKE_CXX_STANDARD 11)
911
set(CMAKE_CXX_STANDARD_REQUIRED 11)
12+
include(GNUInstallDirs)
13+
1014

11-
enable_testing()
1215

1316
if (NOT CMAKE_BUILD_TYPE)
1417
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY VALUE Release)
@@ -17,22 +20,8 @@ endif()
1720
if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
1821
add_definitions(-D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -DWIN32 -D_WINDOWS)
1922

20-
if (NOT DEFINED ICU_ROOT)
21-
find_program(NUGET nuget)
22-
if(NOT NUGET)
23-
file(DOWNLOAD https://dist.nuget.org/win-x86-commandline/latest/nuget.exe ${CMAKE_BINARY_DIR}/nuget.exe)
24-
find_program(NUGET nuget PATHS ${CMAKE_BINARY_DIR})
25-
if (NOT NUGET)
26-
message(FATAL_ERROR "CMake could not find the nuget command line tool. Please install it or provide ICU_ROOT.")
27-
endif()
28-
endif()
29-
30-
# Copy the Nuget config file from source location to the CMake build directory.
31-
configure_file(packages.config.in packages.config COPYONLY)
32-
# Run Nuget using the .config file to install any missing dependencies to the build directory.
33-
execute_process(
34-
COMMAND ${NUGET} restore packages.config -SolutionDirectory ${CMAKE_BINARY_DIR}
35-
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
23+
if (NOT DEFINED ICU_ROOT AND NOT DEFINED FETCHCONTENT_SOURCE_DIR_ICU)
24+
set(ICU_URL https://github.com/unicode-org/icu/releases/download/release-66-1/icu4c-66_1-Win32-MSVC2017.zip)
3625
endif()
3726
endif()
3827

README.md

Lines changed: 67 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ path to it should be specified using the GDLPP environment variable
1919
naming may be needed.) or placed in the same folder as grcompiler.
2020

2121
- GrcRegressionTest is used to regression test grcompiler against a set of
22-
reference GDL files and fonts. The regression tests are typically ran using
22+
reference GDL files and fonts. The regression tests are typically ran using
2323
project files (see below).
2424

2525
### GDLPP #include details
@@ -134,20 +134,20 @@ You will need libc++ and libc++-abi packages.
134134
135135
#### Windows specific details
136136
137-
Visual Studio 2017 added support for handling CMake projects. You can find
137+
Visual Studio 2017 added support for handling CMake projects. You can find
138138
more information and instructions at
139139
[CMake projects in Visual Studio](https://docs.microsoft.com/en-us/cpp/build/cmake-projects-in-visual-studio?view=vs-2019).
140140
141-
TIPS:
142-
- After generating the project files and optionally doing inital building and
143-
testing (above), the easiest way for Visual Studio developers to proceed is to
141+
TIPS:
142+
- After generating the project files and optionally doing inital building and
143+
testing (above), the easiest way for Visual Studio developers to proceed is to
144144
open the `grcompiler.sln` file that cmake generates.
145145
146-
- The Solution Explorer will contain projects for `grcompiler`, `gdlpp`, and
147-
`GrcRegressionTest`, as well as several other projects, some of which are just
146+
- The Solution Explorer will contain projects for `grcompiler`, `gdlpp`, and
147+
`GrcRegressionTest`, as well as several other projects, some of which are just
148148
empty standard test targets that cmake generates.
149149
150-
- Do NOT switch the Solution Explorer to Folder View as that will cause cmake
150+
- Do NOT switch the Solution Explorer to Folder View as that will cause cmake
151151
project generation to be redone using the Ninja generator (see below).
152152
153153
- Right clicking on the grcompiler project and setting it as the Startup
@@ -158,7 +158,7 @@ Project is advisable.
158158
- Right clicking on RUN_TESTS and Building will run the regression tests.
159159
160160
If development with cmake is preferred, in Visual Studio 2019,`File-Open-CMake...`
161-
can be used to open the CMakeCache.txt file. Using `File-Open Folder...' is not
161+
can be used to open the CMakeCache.txt file. Using `File-Open Folder...` is not
162162
advisable, since the Ninja project generator will be used. It seems buggy.
163163
FWIW, it's harder to specify the arguments to use for debugging with cmake
164164
development compared to using the sln file.
@@ -177,57 +177,75 @@ The CMake approach above is strongly encouraged.
177177
The choice of 32- or 64-bit build tools and targets is made by building
178178
from the appropriate Visual Studio command prompt.
179179
180-
To build grcomiler release binaries, from the `compiler` folder:
181-
```
182-
nmake -f makefile.mak
183-
```
184-
185-
To build grcompiler debug binaries:
186-
```
187-
nmake CFG=DEBUG -f makefile.mak
188-
```
180+
To build grcomiler release binaries, from the `compiler` folder:
181+
```
182+
nmake -f makefile.mak
183+
```
189184
190-
TIP: A debug build for ICU from source may be needed too (see below).
185+
To build grcompiler debug binaries:
186+
```
187+
nmake CFG=DEBUG -f makefile.mak
188+
```
191189
192-
Cleaning up, to remove all .obj files without removing the binaries:
193-
```
194-
nmake -f makefile.mak clean
195-
```
190+
TIP: A debug build for ICU from source will be needed too (see below).
196191
197-
To remove the binaries as well:
198-
```
199-
nmake -f makefile.mak realclean
200-
```
192+
Cleaning up, to remove all .obj files without removing the binaries:
193+
```
194+
nmake -f makefile.mak clean
195+
```
201196
197+
To remove the binaries as well:
198+
```
199+
nmake -f makefile.mak realclean
200+
```
202201
This deletes the libraries as well.
203202
204-
To build gdlpp, from the `preprocessor` folder:
205-
```
206-
nmake -f gdlpp.mak
207-
```
203+
To build gdlpp, from the `preprocessor` folder:
204+
```
205+
nmake -f gdlpp.mak
206+
```
208207
209-
To build GrcRegressionTest and run regression tests,
210-
from the `test/GrcRegressionTest` folder:
211-
`nmake -f Makefile.vc`
212-
`cd fonts`
213-
`nmake -f regtest.mak`
208+
To build GrcRegressionTest and run regression tests, from the
209+
`test/GrcRegressionTest` folder:
210+
```
211+
nmake -f Makefile.vc
212+
cd fonts
213+
nmake -f regtest.mak
214+
```
214215
215216
To use Visual Studio, setup a new makefile project and add commands
216217
for building, testing, and debugging using the makefiles indicated above.
217218
218219
## DEPENDENCIES
219220
### ICU
220221
222+
The grcompiler executable has a hard build dependency on ICU. This
223+
dependency may be satisfied via a system supplied dev package as is common on
224+
Linux, or via a pre-built binary distribution archive available from the
225+
[ICU4C project](http://site.icu-project.org/download/).
226+
227+
- CMake:
228+
This will automatically download and unpack any archive URL passed to it
229+
via `ICU_URL`. It will search for ICU includes and libraries in the root
230+
of that archive expecting to find `include`, `lib` and `bin` directories.
231+
If those dirs are deeper inside the archive (e.g. inside usr/local) then
232+
passing the relative archive path in `ICU_ROOT` will cause it to search
233+
there. If you have a local binary copy, e.g. if you are patching ICU too,
234+
you can have it use that instead by passing the path in
235+
`FETCHCONTENT_SOURCE_DIR_ICU`. Lastly passing just `ICU_ROOT` as a
236+
semi-colon separated list of paths to search allows you to use an ICU
237+
distribution where executables, includes and libraries aren't neatly
238+
arranged. This might be the case if you want to pass both debug and
239+
release builds of ICU on Windows, in which case it will link the
240+
appopriate version.
241+
221242
#### Linux
222243
223244
You should use your distributions package manager to install icu-dev package.
224245
225246
- CMake:
226-
It will automatically find the system dev package installed by you package
227-
manager. Setting the CMake variable ICU_ROOT to an abolute path will
228-
override this process and use the built copy located at the provided path.
229-
This can be set by passing `-DICU_ROOT=<path to built ICU files>` to the
230-
`cmake` configuration invocation.
247+
By default it will automatically find the system dev package installed by
248+
your package manager via the use of pkg-config.
231249
- autotools:
232250
This will auto detect the icu installation via the use of pkg-config
233251
To overide the detection you need to provide compiler and linker flags via
@@ -236,34 +254,20 @@ You should use your distributions package manager to install icu-dev package.
236254
237255
#### Windows
238256
239-
The Graphite compiler requires library modules from ICU.
240-
241-
- CMake:
242-
The CMakeLists.txt will automatically fetch the icu4c.v140 nuget package
243-
for you and also a copy of nuget if it's not installed. Modify
244-
`packages.config.in` to update the version. Setting the ICU_ROOT CMake
245-
variable to the semicolon separated list of directories which contain the
246-
`.lib` stub files for the ICU DLLS and the include directory allows you to
247-
use the official pre-built ICU distribution. In addition you will need to
248-
set ICU_REDIST_ROOT to the path where the DLLs are if you want testing to
249-
work as the build script will need to copy them.
250-
.e.g if you unzip the downloaded ICU distribution into a dir called `icu`
251-
in the top of the source tree you would pass these to `cmake`:
252-
`-DICU_ROOT="..\icu\lib;..\icu\include"` and
253-
`-DICU_REDIST_ROOT="..\icu\bin"` in addition to the usual arguments.
254-
- Nmake:
255-
You will need to download the ICU binaries from the following web
256-
site: http://site.icu-project.org/download/
257-
- Create an icu folder under this project's top level folder and unzip
257+
- CMake:
258+
If no `ICU_URL`, `FETCHCONTENT_SOURCE_DIR_ICU` or `ICU_ROOT` parameter is
259+
passed then it will automatically set `ICU_URL` to a recent release and
260+
proceed as above, by downloading and using that archive.
261+
- Nmake:
262+
- Create an icu folder under this project's top level folder and unzip
258263
the archive into it.
259-
- makefile.mak copies the needed binaries to the folder where grcompiler
264+
- makefile.mak copies the needed binaries to the folder where grcompiler
260265
is built. You may need to modify the file names for the icu/bin/*.dll
261266
files in makefile.mak since the file names include the version number
262267
of icu.
263-
- The icu project only supplies release versions of the binaries. So, when
268+
- The icu project only supplies release versions of the binaries. So, when
264269
building a debug version of grcompiler, it is linked to release versions
265270
of the ICU dlls. To link to debug versions instead, icu binaries have to be
266271
built from source and makefile.mak adjusted to use them. In the icu source,
267272
there is a VisualStudio file in the source\allinone directory that can be
268273
used to build the binaries. The "common" project is the one to build.
269-
Good luck!

compiler/CMakeLists.txt

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
11
project(compiler VERSION 5.2)
22
cmake_policy(SET CMP0074 NEW)
33

4-
if (DEFINED NUGET)
5-
file(GLOB _icu_nuget_libs_paths "${CMAKE_BINARY_DIR}/packages/icu4c.v*/build/native/lib/*/*")
6-
file(GLOB _icu_nuget_incs_paths "${CMAKE_BINARY_DIR}/packages/icu4c.v*/build/native/include")
7-
file(GLOB ICU_REDIST_ROOT "${CMAKE_BINARY_DIR}/packages/icu4c.v*.redist.*/build/native/bin")
8-
set(ICU_REDIST_ROOT "${ICU_REDIST_ROOT}/${CMAKE_VS_PLATFORM_NAME}")
4+
FetchContent_Declare(icu URL ${ICU_URL})
95

10-
set(ICU_ROOT
11-
${_icu_nuget_libs_paths}
12-
${_icu_nuget_incs_paths}
13-
${ICU_ROOT})
14-
message(STATUS "Using NuGet ICU package.")
6+
if (DEFINED ICU_URL OR DEFINED FETCHCONTENT_SOURCE_DIR_ICU)
7+
FetchContent_GetProperties(icu)
8+
if (NOT icu_POPULATED)
9+
message(STATUS "Fetching: " ${ICU_URL})
10+
FetchContent_Populate(icu)
11+
endif()
12+
13+
if (icu_POPULATED)
14+
set(ICU_ROOT ${icu_SOURCE_DIR}/${ICU_ROOT})
15+
else()
16+
set(ICU_ROOT "")
17+
endif()
1518
endif()
1619

17-
find_package(ICU REQUIRED COMPONENTS uc i18n)
20+
find_package(ICU REQUIRED COMPONENTS uc i18n data)
1821
message(STATUS "ICU Libraries: " ${ICU_VERSION})
1922

2023
add_subdirectory(Generic)
@@ -53,16 +56,19 @@ add_executable(grcompiler
5356
PostParser.cpp
5457
$<TARGET_OBJECTS:TtfUtil>
5558
main.cpp)
56-
target_link_libraries(grcompiler ${ICU_I18N_LIBRARY} ${ICU_UC_LIBRARY} generic parser lz4)
5759

5860
if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
5961
target_compile_options(grcompiler PRIVATE /Zc:wchar_t- /W3 /EHsc)
62+
endif()
63+
64+
target_link_libraries(grcompiler ICU::uc ICU::i18n generic parser lz4)
6065

61-
if (DEFINED ICU_REDIST_ROOT)
62-
get_filename_component(ICU_REDIST_ROOT ${ICU_REDIST_ROOT} ABSOLUTE)
66+
if (icu_POPULATED)
67+
if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
68+
file(GLOB_RECURSE _icu_dlls "${icu_SOURCE_DIR}/**${CMAKE_SHARED_LIBRARY_SUFFIX}")
6369
add_custom_command(TARGET grcompiler POST_BUILD
64-
COMMAND ${CMAKE_COMMAND} -E copy_directory
65-
"${ICU_REDIST_ROOT}/$<$<BOOL:${NUGET}>:$<CONFIGURATION>>"
70+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
71+
${_icu_dlls}
6672
$<TARGET_FILE_DIR:grcompiler>)
6773
endif()
6874
endif()

packages.config.in

Lines changed: 0 additions & 5 deletions
This file was deleted.

test/GrcRegressionTest/CMakeLists.txt

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ function(compile_test FONT VERSION PSNAME)
2525
add_test(NAME compile_${FONT}
2626
COMMAND grcompiler -D -v${VERSION} ${ARGN} -e ${PROJECT_BINARY_DIR}/${FONT}.gdlerr.txt ${FONT_SOURCE_DIR}/${_input}Main.gdl ${FONT_SOURCE_DIR}/${_input}Input.ttf ${FONT}.ttf ${PSNAME})
2727
set_tests_properties(compile_${FONT} PROPERTIES
28-
ENVIRONMENT GDLPP=$<TARGET_FILE:gdlpp>
28+
ENVIRONMENT "GDLPP=$<TARGET_FILE:gdlpp>;LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${ICU_INCLUDE_DIR}/../lib"
2929
# ATTACHED_FILES ${PROJECT_BINARY_DIR}/${FONT}.gdlerr.log
3030
REQUIRED_FILES "${FONT_SOURCE_DIR}/${_input}Input.ttf;${FONT_SOURCE_DIR}/${_input}Main.gdl"
3131
WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
@@ -50,21 +50,14 @@ function(compile_test FONT VERSION PSNAME)
5050
endfunction()
5151

5252
function(get_icu_dirs)
53-
if(ICU_INCLUDE_DIR AND EXISTS "${ICU_INCLUDE_DIR}/unicode/uvernum.h")
54-
file(STRINGS "${ICU_INCLUDE_DIR}/unicode/uvernum.h" icu_header_str
55-
REGEX "^#define[\t ]+U_ICU_VERSION[\t ]+\".*\".*")
56-
57-
string(REGEX REPLACE "^#define[\t ]+U_ICU_VERSION[\t ]+\"([^ \\n.]*)(\.[^ \\n]*)?\".*"
58-
"\\1" icu_version_string "${icu_header_str}")
59-
endif()
60-
53+
string(REGEX MATCH "^[0-9]+" icu_major_version ${ICU_VERSION})
6154
file(GLOB icuders RELATIVE ${FONT_SOURCE_DIR} CONFIGURE_DEPENDS
6255
${FONT_SOURCE_DIR}/icu*)
6356
list(TRANSFORM icuders REPLACE "icu([0-9]+)$" "\\1")
6457
list(SORT icuders)
6558
list(REVERSE icuders)
6659
foreach(ver IN LISTS icuders)
67-
if (${ver} LESS_EQUAL ${icu_version_string})
60+
if (${ver} LESS_EQUAL ${icu_major_version})
6861
list(APPEND ICUDIRS "${ver}")
6962
endif()
7063
endforeach()

0 commit comments

Comments
 (0)