2

I am trying out to use CMake to cross-compile a program, but it failed with this message:

/bin/sh: 1: Syntax error: ";;" unexpected 

The program compiles perfectly with a raw Makefile

Here is my CMake file:

cmake_minimum_required(VERSION 3.9) project(my_target LANGUAGES CUDA CXX C) include(CheckLanguage) check_language(CUDA) # STD if (NOT DEFINED CMAKE_CUDA_STANDARD) set(CMAKE_CUDA_STANDARD 11) set(CMAKE_CUDA_STANDARD_REQUIRED ON) endif() find_package(Poco REQUIRED Foundation Util) # Flags set ( CMAKE_C_STANDARD 11 ) set( CMAKE_CXX_STANDARD 11 ) set( CMAKE_C_FLAGS ${CMAKE_C_FLAGS} -c -Wall -fopenmp ) set( CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -c -Wall -fopenmp ) set( CMAKE_CUDA_FLAGS ${CMAKE_NVCC_FLAGS} --ccbin $(CMAKE_CXX_COMPILER) -O2 -gencode -std=c++11 -dc -Werror deprecated-declarations ) # Compile Objects file(GLOB_RECURSE src_c src/*.c ) file(GLOB_RECURSE src_cpp src/*.cpp) file(GLOB_RECURSE src_cu src/*.cu ) file(GLOB_RECURSE src_h src/*.h ) add_library(cobjs STATIC ${src_c} ${src_h} ) add_library(cppobjs STATIC ${src_cpp} ${src_h}) add_library(cuobjs STATIC ${src_cu} ${src_h} ) target_compile_options(cobjs PUBLIC ${CMAKE_C_FLAGS} ) target_compile_options(cppobjs PUBLIC ${CMAKE_CXX_FLAGS}) target_compile_options(cuobjs PUBLIC ${CMAKE_NVCC_FLAGS}) set_target_properties( cuobjs PROPERTIES CUDA_SEPARABLE_COMPILATION ON) add_executable(my_target ${cobjs} ${cppobjs} ${cuobjs} ${src_h} ) # Include Dirs target_include_directories(cobjs PUBLIC include src ) target_include_directories(cppobjs PUBLIC include src ) target_include_directories(cuobjs PUBLIC include src ) target_include_directories(my_target PUBLIC include src ) link_directories( ${POCO_HOME} ${METIS_HOME} ) target_link_libraries(my_target PUBLIC cobjs cppobjs cuobjs -lPocoFoundation -lPocoUtil -lpthread -lgomp -lmetis ) 

And the working Makefile:

#=============================================================================== CUDA_PATH := /usr/local/cuda METIS_PATH := ${METIS_HOME} POCO_PATH := ${POCO_HOME} # D-debug R-release COMPILEMD := R EXE := coupled.exe CC := gcc CXX := g++ #=============================================================================== DIR_BIN := bin DIR_SRC := src CCFLAGS := -Iinclude -I$(DIR_SRC) -std=c11 -c -Wall -fopenmp CXXFLAGS := -I$(CUDA_PATH)/include -I$(METIS_PATH)/include -I$(POCO_PATH)/include -Iinclude -I$(DIR_SRC) -std=c++11 -c -Wall -fopenmp NVCCFLAGS := -I$(POCO_PATH)/include -I$(DIR_SRC) -std=c++11 -dc -Werror deprecated-declarations LDFLAGS := -L$(METIS_PATH)/lib -lmetis -L$(POCO_PATH)/lib -lPocoUtil -lPocoFoundation -Llib -ltecio -lpthread -lgomp BASENM := $(basename $(EXE)) SUFFIX := $(suffix $(EXE)) SRC_C := $(shell find $(DIR_SRC) -name *.c) SRC_CPP := $(shell find $(DIR_SRC) -name *.cpp) SRC_CU := $(shell find $(DIR_SRC) -name *.cu) OBJ_C := $(SRC_C:%.c=%.o) OBJ_CPP := $(SRC_CPP:%.cpp=%.o) OBJ_CU := $(SRC_CU:%.cu=%.o) ifeq ($(COMPILEMD), D) CCFLAGS += -D_DEBUG -g CXXFLAGS += -D_DEBUG -g NVCCFLAGS += -D_DEBUG -g -G else ifeq ($(COMPILEMD), R) CCFLAGS += -DNDEBUG -O2 CXXFLAGS += -DNDEBUG -O2 NVCCFLAGS += -DNDEBUG -O2 else $(error error COMPILEMD($(COMPILEMD))) endif CCFLAGS += -DKS_FP_DOUBLE -march=native CXXFLAGS += -DKS_FP_DOUBLE -march=native NVCCFLAGS += -DKS_FP_DOUBLE BASENM := $(BASENM)DP$(COMPILEMD) ifeq ($(SRC_CU), ) LD := $(CXX) else NVCC := $(CUDA_PATH)/bin/nvcc -ccbin $(CXX) DEVICE_SM := 50 52 60 61 #70 75 $(foreach SM,$(DEVICE_SM),$(eval NVCCFLAGS += -gencode arch=compute_$(SM),code=sm_$(SM))) $(foreach SM,$(DEVICE_SM),$(eval LDFLAGS += -gencode arch=compute_$(SM),code=sm_$(SM))) LD := $(NVCC) endif OBJ := $(OBJ_C) $(OBJ_CPP) $(OBJ_CU) EXE := $(DIR_BIN)/$(BASENM)$(SUFFIX) #=============================================================================== all: $(EXE) .PHONY: all clean cleanall $(EXE): $(OBJ) @mkdir -p $(DIR_BIN) $(LD) $^ $(LDFLAGS) -o $@ $(OBJ_C): %.o: %.c $(CC) $< $(CCFLAGS) -o $@ $(OBJ_CPP): %.o: %.cpp $(CXX) $< $(CXXFLAGS) -o $@ $(OBJ_CU): %.o: %.cu $(NVCC) $< $(NVCCFLAGS) -o $@ clean: -rm -rf $(OBJ) $(EXE) cleanall: -rm -rf $(OBJ) $(DIR_BIN)/*log $(DIR_BIN)/*.exe $(DIR_BIN)/*.dat 

I am sorry that I could not provide the project's source code.

I am very new to CMake, and any help will be appreciated!

EDIT

I tried the solutions given by @squareskittles which seems to solve the /bin/sh: 1: Syntax error: ";;" unexpected problem. But I got a new error which says:

c++: fatal error: no input files 

Yet in the corresponding build.make file the error line writes:

/usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o <path-to-my-cpp>/my.cpp.o -c <path-to-my-cpp>/my.cpp 

EDIT2

Thanks to @squareskittles's answer, I finally get to understand how CMake works. There are actually more than one incorrect parts in the CMakeLists.txt file:

  1. CMake adds automatically -c flags to C and C++ compilers so there is no need to add it manually.

  2. It is preferred to use add_compile_options() to add compilation flags than set(CMAKE_<LANG>_FLAGS ...).

  3. link_directories should always go before add_library() and add_executable(). A modern approach instead is to use find_library(), see here.

  4. I finally gave up to manually write multiple stage compilation as I did in my Makefile, and instead added all source files in add_executable(). CMake seems to have handled the different cases perfectly.

My final working version:

cmake_minimum_required(VERSION 3.9) project(my_target LANGUAGES CUDA CXX C) # STD if (NOT DEFINED CMAKE_CUDA_STANDARD) set(CMAKE_CUDA_STANDARD 11) set(CMAKE_CUDA_STANDARD_REQUIRED ON) endif() find_package(Poco REQUIRED Foundation Util) # Flags set ( CMAKE_C_STANDARD 11 ) set( CMAKE_CXX_STANDARD 11 ) # Compile Objects file(GLOB_RECURSE src_c src/*.c ) file(GLOB_RECURSE src_cpp src/*.cpp) file(GLOB_RECURSE src_cu src/*.cu ) file(GLOB_RECURSE src_h src/*.h ) # message(STATUS "src_c = ${src_c}" ) # message(STATUS "src_cpp = ${src_cpp}") # message(STATUS "src_cu = ${src_cu}" ) # message(STATUS "src_h = ${src_h}" ) add_definitions(-DKS_FP_DOUBLE) link_directories( ${POCO_HOME} ${METIS_HOME} ) add_executable(my_target ${src_c} ${src_cpp} ${src_cu} ${src_h} ) # Include Dirs target_include_directories(my_target PUBLIC include src ) set_target_properties(my_target PROPERTIES CUDA_SEPARABLE_COMPILATION ON ) target_link_libraries(my_target PUBLIC # cobjs # cppobjs # cuobjs -lPocoFoundation -lPocoUtil -lpthread -lgomp -lmetis ) 

1 Answer 1

2

When you set the CMake compiler flag variables (or any other CMake variable), you don't need to insert semicolons ; to separate the arguments/flags. CMake will recognize newlines and spaces in the set() command and handle this for you. From the docs:

Multiple arguments will be joined as a semicolon-separated list to form the actual variable value to be set.

Try this:

set( CMAKE_C_FLAGS ${CMAKE_C_FLAGS} -c -Wall -fopenmp ) set( CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -c -Wall -fopenmp ) set( CMAKE_CUDA_FLAGS ${CMAKE_NVCC_FLAGS} --ccbin $(CMAKE_CXX_COMPILER) -O2 -gencode -std=c++11 -dc -Werror deprecated-declarations ) 

There is one more issue with the CMake file you posted. The add_executable() command only takes source files as arguments. You cannot use previously-defined targets as arguments. Try modifying your call to add_executable(); you already compile the C, C++, and Cuda sources into static libraries with your calls to add_library(), so maybe there is simply a main.cpp (defining your call to main()) you can include in this call:

add_executable(my_target main.cpp ${src_h} ) 
Sign up to request clarification or add additional context in comments.

3 Comments

Thank u for replying @squareskittles, i tried your suggestion and get another error... Please kindly see my edit.
@NikoZ. I expanded my answer. I did not see the other issue in your CMake originally.
Thanks @squareskittles, I tried your suggestion and finally make it work! I have put the working CMakeLists.txt in my EDIT2.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.