Skip to content

Commit c8eaf76

Browse files
committed
Improve offline build experience for forge developers
The following common scenarios(majority we think) are covered with this change. - Developer has cloud connection always. - Developer has cloud connection for initial cmake run, but not later. - Developer has lost cloud connection for a while after the initial successful cmake run but regained the connection later. - Developer is doing an completely disconnected build using the source tarball we generate and attach to our release assets. When the developer wants to do an offline build for a specific commit other than release tags, they would have to generate the relevant source tarball themselves. The commands required to do the same can be found from the following ci workflow file in our repository. .github/workflows/release_src_artifact.yml The source tarball generation CI job has also been changed to reflect the change in external dependencies location. (cherry picked from commit da1ffc3)
1 parent 8d5808e commit c8eaf76

File tree

6 files changed

+187
-80
lines changed

6 files changed

+187
-80
lines changed

.github/workflows/release_src_artifact.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ jobs:
5252
rm -rf forge-full-${FG_VER}/.github
5353
rm forge-full-${FG_VER}/.gitmodules
5454
cd forge-full-${FG_VER}/build/
55+
cp -r ./examples/third_party/cl2hpp ../extern/cl2hpp
5556
shopt -s extglob
5657
rm -r !(extern)
5758
cd ./extern

CMakeLists.txt

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,10 @@ if(Boost_FOUND AND NOT TARGET Boost::boost)
6868
endif(Boost_FOUND AND NOT TARGET Boost::boost)
6969

7070
if(NOT TARGET glad::glad) # find_package(glad) failed
71-
FetchContent_Declare(
72-
${glad_prefix}
73-
GIT_REPOSITORY https://github.com/arrayfire/glad.git
74-
GIT_TAG obj_lib
75-
)
76-
fg_check_and_populate(${glad_prefix})
71+
fg_dep_check_and_populate(${glad_prefix}
72+
URI https://github.com/arrayfire/glad.git
73+
REF obj_lib
74+
)
7775
add_subdirectory(${${glad_prefix}_SOURCE_DIR} ${${glad_prefix}_BINARY_DIR})
7876

7977
add_library(forge_glad STATIC $<TARGET_OBJECTS:glad_obj_lib>)
@@ -86,17 +84,18 @@ else()
8684
add_library(forge_glad ALIAS glad::glad)
8785
endif()
8886

89-
if(NOT TARGET glm::glm AND NOT TARGET glm) # find_package(glm) failed
90-
FetchContent_Declare(
91-
${glm_prefix}
92-
GIT_REPOSITORY https://github.com/g-truc/glm.git
93-
GIT_TAG 0.9.9.8
94-
)
95-
fg_check_and_populate(${glm_prefix})
96-
add_library(glm INTERFACE IMPORTED)
97-
set_target_properties(glm PROPERTIES
98-
INTERFACE_INCLUDE_DIRECTORIES "${${glm_prefix}_SOURCE_DIR}"
99-
)
87+
add_library(forge_glm INTERFACE)
88+
if(TARGET glm::glm)
89+
target_include_directories(forge_glm
90+
SYSTEM INTERFACE
91+
$<TARGET_PROPERTY:glm::glm,INTERFACE_INCLUDE_DIRECTORIES>
92+
)
93+
else() # find_package(glm) failed
94+
fg_dep_check_and_populate(${glm_prefix}
95+
URI https://github.com/g-truc/glm.git
96+
REF 0.9.9.8
97+
)
98+
target_include_directories(forge_glm INTERFACE "${${glm_prefix}_SOURCE_DIR}")
10099
endif()
101100

102101
add_subdirectory(src/backend/common)

CMakeModules/ForgeConfigureDepsVars.cmake

Lines changed: 110 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,53 @@
55
# The complete license agreement can be obtained at:
66
# http://arrayfire.com/licenses/BSD-3-Clause
77

8-
option(FG_BUILD_OFFLINE "Build Forge assuming there is no network" OFF)
8+
file(DOWNLOAD
9+
"https://github.com/arrayfire/forge/blob/v1.0.0/CMakeLists.txt"
10+
"${Forge_BINARY_DIR}/download_copy_cmakelists.stamp"
11+
STATUS fg_check_result
12+
TIMEOUT 4
13+
)
14+
list(GET fg_check_result 0 fg_is_connected)
15+
if(${fg_is_connected})
16+
set(BUILD_OFFLINE ON)
17+
# Turn ON disconnected flag when connected to cloud
18+
set(FETCHCONTENT_FULLY_DISCONNECTED ON CACHE BOOL
19+
"Disable Download/Update stages of FetchContent workflow" FORCE)
20+
21+
message(STATUS "No cloud connection. Attempting offline build if dependencies are available")
22+
else()
23+
set(BUILD_OFFLINE OFF)
24+
# Turn OFF disconnected flag when connected to cloud
25+
# This is required especially in the following scenario:
26+
# - cmake run successfully first
27+
# - lost connection, but development can still be done
28+
# - Now, connection regained. Hence updates should be allowed
29+
set(FETCHCONTENT_FULLY_DISCONNECTED OFF CACHE BOOL
30+
"Disable Download/Update stages of FetchContent workflow" FORCE)
31+
endif()
32+
33+
# Track dependencies download persistently across multiple
34+
# cmake configure runs. *_POPULATED variables are reset for each
35+
# cmake run to 0. Hence, this internal cache value is needed to
36+
# check for already (from previous cmake run's) populated data
37+
# during the current cmake run if it looses network connection.
38+
set(FG_INTERNAL_DOWNLOAD_FLAG OFF CACHE BOOL "Dependencies Download Tracker Flag")
939

1040
# Override fetch content base dir before including AFfetch_content
1141
set(FETCHCONTENT_BASE_DIR "${Forge_BINARY_DIR}/extern" CACHE PATH
1242
"Base directory where Forge dependencies are downloaded and/or built" FORCE)
1343

1444
include(ForgeFetchContent)
1545

16-
macro(set_and_mark_depname var name)
46+
mark_as_advanced(
47+
FG_INTERNAL_DOWNLOAD_FLAG
48+
FETCHCONTENT_BASE_DIR
49+
FETCHCONTENT_QUIET
50+
FETCHCONTENT_FULLY_DISCONNECTED
51+
FETCHCONTENT_UPDATES_DISCONNECTED
52+
)
53+
54+
macro(set_and_mark_depnames_advncd var name)
1755
string(TOLOWER ${name} ${var})
1856
string(TOUPPER ${name} ${var}_ucname)
1957
mark_as_advanced(
@@ -22,31 +60,79 @@ macro(set_and_mark_depname var name)
2260
)
2361
endmacro()
2462

25-
mark_as_advanced(
26-
FETCHCONTENT_BASE_DIR
27-
FETCHCONTENT_QUIET
28-
FETCHCONTENT_FULLY_DISCONNECTED
29-
FETCHCONTENT_UPDATES_DISCONNECTED
30-
)
63+
set_and_mark_depnames_advncd(glad_prefix "fg_glad")
64+
set_and_mark_depnames_advncd(glm_prefix "fg_glm")
3165

32-
set_and_mark_depname(glad_prefix "fg_glad")
33-
set_and_mark_depname(glm_prefix "fg_glm")
66+
macro(fg_dep_check_and_populate dep_prefix)
67+
set(single_args URI REF)
68+
cmake_parse_arguments(fdcp_args "" "${single_args}" "" ${ARGN})
3469

35-
if(FG_BUILD_OFFLINE)
36-
macro(set_fetchcontent_src_dir prefix_var dep_name)
37-
set(FETCHCONTENT_SOURCE_DIR_${${prefix_var}_ucname}
38-
"${FETCHCONTENT_BASE_DIR}/${${prefix_var}}-src" CACHE PATH
39-
"Source directory for ${dep_name} dependency")
40-
mark_as_advanced(FETCHCONTENT_SOURCE_DIR_${${prefix_var}_ucname})
41-
endmacro()
70+
if("${fdcp_args_URI}" STREQUAL "")
71+
message(FATAL_ERROR [=[
72+
Cannot check requested dependency source's availability.
73+
Please provide a valid URI(almost always a URL to a github repo).
74+
Note that the above error message if for developers of Forge.
75+
]=])
76+
endif()
4277

43-
set_fetchcontent_src_dir(assets_prefix "glad")
44-
set_fetchcontent_src_dir(testdata_prefix "glm")
45-
endif()
78+
string(FIND "${fdcp_args_REF}" "=" fdcp_has_algo_id)
4679

47-
macro(fg_check_and_populate prefix)
48-
FetchContent_GetProperties(${prefix})
49-
if(NOT ${prefix}_POPULATED)
50-
FetchContent_Populate(${prefix})
80+
if(${BUILD_OFFLINE} AND NOT ${FG_INTERNAL_DOWNLOAD_FLAG})
81+
if(NOT ${fdcp_has_algo_id} EQUAL -1)
82+
FetchContent_Populate(${dep_prefix}
83+
QUIET
84+
URL ${fdcp_args_URI}
85+
URL_HASH ${fdcp_args_REF}
86+
DOWNLOAD_COMMAND \"\"
87+
UPDATE_DISCONNECTED ON
88+
SOURCE_DIR "${Forge_SOURCE_DIR}/extern/${dep_prefix}-src"
89+
BINARY_DIR "${Forge_BINARY_DIR}/extern/${dep_prefix}-build"
90+
SUBBUILD_DIR "${Forge_BINARY_DIR}/extern/${dep_prefix}-subbuild"
91+
)
92+
elseif("${fdcp_args_REF}" STREQUAL "")
93+
FetchContent_Populate(${dep_prefix}
94+
QUIET
95+
URL ${fdcp_args_URI}
96+
DOWNLOAD_COMMAND \"\"
97+
UPDATE_DISCONNECTED ON
98+
SOURCE_DIR "${Forge_SOURCE_DIR}/extern/${dep_prefix}-src"
99+
BINARY_DIR "${Forge_BINARY_DIR}/extern/${dep_prefix}-build"
100+
SUBBUILD_DIR "${Forge_BINARY_DIR}/extern/${dep_prefix}-subbuild"
101+
)
102+
else()
103+
# The left over alternative is assumed to be a cloud hosted git repository
104+
FetchContent_Populate(${dep_prefix}
105+
QUIET
106+
GIT_REPOSITORY ${fdcp_args_URI}
107+
GIT_TAG ${fdcp_args_REF}
108+
DOWNLOAD_COMMAND \"\"
109+
UPDATE_DISCONNECTED ON
110+
SOURCE_DIR "${Forge_SOURCE_DIR}/extern/${dep_prefix}-src"
111+
BINARY_DIR "${Forge_BINARY_DIR}/extern/${dep_prefix}-build"
112+
SUBBUILD_DIR "${Forge_BINARY_DIR}/extern/${dep_prefix}-subbuild"
113+
)
114+
endif()
115+
else()
116+
if(NOT ${fdcp_has_algo_id} EQUAL -1)
117+
FetchContent_Declare(${dep_prefix}
118+
URL ${fdcp_args_URI}
119+
URL_HASH ${fdcp_args_REF}
120+
)
121+
elseif("${fdcp_args_REF}" STREQUAL "")
122+
FetchContent_Declare(${dep_prefix}
123+
URL ${fdcp_args_URI}
124+
)
125+
else()
126+
# The left over alternative is assumed to be a cloud hosted git repository
127+
FetchContent_Declare(${dep_prefix}
128+
GIT_REPOSITORY ${fdcp_args_URI}
129+
GIT_TAG ${fdcp_args_REF}
130+
)
131+
endif()
132+
FetchContent_GetProperties(${dep_prefix})
133+
if(NOT ${dep_prefix}_POPULATED)
134+
FetchContent_Populate(${dep_prefix})
135+
endif()
136+
set(FG_INTERNAL_DOWNLOAD_FLAG ON CACHE BOOL "Dependencies Download Tracker Flag" FORCE)
51137
endif()
52138
endmacro()

CMakeModules/ForgeInternalUtils.cmake

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -93,24 +93,8 @@ function(fg_set_target_compilation_props target)
9393
SYSTEM PRIVATE
9494
$<TARGET_PROPERTY:Boost::boost,INTERFACE_INCLUDE_DIRECTORIES>
9595
$<TARGET_PROPERTY:forge_glad,INTERFACE_INCLUDE_DIRECTORIES>
96+
$<TARGET_PROPERTY:forge_glm,INTERFACE_INCLUDE_DIRECTORIES>
9697
)
97-
# As imported targets can't be aliased until CMake 3.11, below is a temporary
98-
# work around until we move to a CMake version >= 3.11
99-
if(TARGET glm::glm)
100-
target_include_directories(${target}
101-
SYSTEM PRIVATE
102-
$<TARGET_PROPERTY:glm::glm,INTERFACE_INCLUDE_DIRECTORIES>
103-
)
104-
elseif(TARGET glm)
105-
target_include_directories(${target}
106-
SYSTEM PRIVATE
107-
$<TARGET_PROPERTY:glm,INTERFACE_INCLUDE_DIRECTORIES>
108-
)
109-
else()
110-
# Ideally it wouldn't reach here, just in case of corner case
111-
# I couldn't think of or someother cmake bug
112-
message(FATAL_ERROR "Please install glm dependency")
113-
endif()
11498
target_include_directories(${target}
11599
PUBLIC
116100
$<INSTALL_INTERFACE:${FG_INSTALL_INC_DIR}>
Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,56 @@
1-
set(cl2hpp_header
1+
file(DOWNLOAD
2+
"https://github.com/arrayfire/forge/blob/master/.github/LICENSE"
3+
"${PROJECT_BINARY_DIR}/LICENSE.md"
4+
STATUS fg_check_result
5+
TIMEOUT 4
6+
)
7+
list(GET fg_check_result 0 fg_is_connected)
8+
9+
set(cl2hpp_extern_header
10+
"${Forge_SOURCE_DIR}/extern/cl2hpp/include/CL/cl2.hpp")
11+
set(cl2hpp_download_header
212
"${PROJECT_BINARY_DIR}/third_party/cl2hpp/include/CL/cl2.hpp")
3-
if (OpenCL_FOUND)
4-
if (NOT EXISTS ${cl2hpp_header})
5-
set(file_url
6-
"https://github.com/KhronosGroup/OpenCL-CLHPP/releases/download/v2.0.10/cl2.hpp")
7-
file(DOWNLOAD ${file_url} ${cl2hpp_header}
8-
EXPECTED_HASH MD5=c38d1b78cd98cc809fa2a49dbd1734a5
9-
STATUS download_result)
10-
list(GET download_result 0 download_code)
11-
if (NOT ${download_code} EQUAL 0)
12-
file(REMOVE ${cl2hpp_header}) #empty file have to be removed
13-
message(FATAL_ERROR "Failed to download cl2hpp header")
13+
14+
if(${fg_is_connected} AND NOT EXISTS ${cl2hpp_download_header})
15+
if(EXISTS ${cl2hpp_extern_header})
16+
get_filename_component(download_dir ${cl2hpp_extern_header} DIRECTORY)
17+
message(STATUS "Found cl2.hpp header at: ${download_dir}")
18+
if (NOT TARGET OpenCL::cl2hpp)
19+
add_library(OpenCL::cl2hpp IMPORTED INTERFACE GLOBAL)
20+
set_target_properties(OpenCL::cl2hpp PROPERTIES
21+
INTERFACE_INCLUDE_DIRECTORIES "${download_dir}/..")
22+
endif ()
23+
else()
24+
message(FATAL_ERROR [=[
25+
Offline builds require already available cl2hpp header. Please
26+
download the file from and place it at the below path path under
27+
project root directory.
28+
29+
Download URL: https://github.com/KhronosGroup/OpenCL-CLHPP/releases/download/v2.0.10/cl2.hpp
30+
Target Location: extern/cl2hpp/include/CL
31+
]=])
32+
endif()
33+
else()
34+
# Any CMakeLists.txt file including this file should call find_package(OpenCL)
35+
if (OpenCL_FOUND)
36+
if (NOT EXISTS ${cl2hpp_download_header})
37+
set(file_url
38+
"https://github.com/KhronosGroup/OpenCL-CLHPP/releases/download/v2.0.10/cl2.hpp")
39+
file(DOWNLOAD ${file_url} ${cl2hpp_download_header}
40+
EXPECTED_HASH MD5=c38d1b78cd98cc809fa2a49dbd1734a5
41+
STATUS download_result)
42+
list(GET download_result 0 download_code)
43+
if (NOT ${download_code} EQUAL 0)
44+
file(REMOVE ${cl2hpp_download_header}) #empty file have to be removed
45+
message(FATAL_ERROR "Failed to download cl2hpp header")
46+
endif ()
47+
endif ()
48+
get_filename_component(download_dir ${cl2hpp_download_header} DIRECTORY)
49+
message(STATUS "Found cl2.hpp header at: ${download_dir}")
50+
if (NOT TARGET OpenCL::cl2hpp)
51+
add_library(OpenCL::cl2hpp IMPORTED INTERFACE GLOBAL)
52+
set_target_properties(OpenCL::cl2hpp PROPERTIES
53+
INTERFACE_INCLUDE_DIRECTORIES "${download_dir}/..")
1454
endif ()
1555
endif ()
16-
get_filename_component(download_dir ${cl2hpp_header} DIRECTORY)
17-
message(STATUS "Found cl2.hpp header at: ${download_dir}")
18-
if (NOT TARGET OpenCL::cl2hpp)
19-
add_library(OpenCL::cl2hpp IMPORTED INTERFACE GLOBAL)
20-
set_target_properties(OpenCL::cl2hpp PROPERTIES
21-
INTERFACE_INCLUDE_DIRECTORIES "${download_dir}/..")
22-
endif ()
23-
endif ()
56+
endif()

src/backend/CMakeLists.txt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,19 @@ if(FG_WITH_FREEIMAGE)
5656
endif()
5757
endif()
5858

59-
6059
target_link_libraries(${BkndTargetName}
6160
PRIVATE
6261
Boost::boost
63-
forge_glad
6462
${FREETYPE_LIBRARIES}
6563
${CMAKE_DL_LIBS}
6664
)
6765

66+
if(TARGET glad::glad)
67+
target_link_libraries(${BkndTargetName} PRIVATE glad::glad)
68+
else()
69+
target_link_libraries(${BkndTargetName} PRIVATE forge_glad)
70+
endif()
71+
6872
if(UNIX)
6973
target_link_libraries(${BkndTargetName}
7074
PRIVATE

0 commit comments

Comments
 (0)