# ISPC Language support

**URL:** https://discourse.cmake.org/t/ispc-language-support/673
**Category:** Development
**Created:** [February 21, 2020, 12:56am UTC](https://discourse.cmake.org/t/ispc-language-support/673 "2020-02-21T00:56:34Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![Lectem](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lectem/32/380_2.png) [@Lectem](https://discourse.cmake.org/u/Lectem)
#### Post date: [February 21, 2020, 12:56am UTC](https://discourse.cmake.org/t/ispc-language-support/673/1 "2020-02-21T00:56:34Z")

</div>

Hi,

I’m trying to add support for the [ISPC](https://ispc.github.io) language (and compiler) to cmake.  
I based my first iteration from what I could gather from the ASM, Fortran and CUDA languages modules, but sadly it seems I am missing something.

The files are available here: [https://github.com/Lectem/cmake-ispc-support](https://github.com/Lectem/cmake-ispc-support)

The compiler is detected correctly, seems to work, however files are not compiled.  
I do set the `CMAKE_ISPC_SOURCE_FILE_EXTENSIONS` variable to ispc but only my .cpp files are compiled to .obj, and the .ispc file is ignored.

This is the output from cmake configuration:

```
-- Building for: Visual Studio 16 2019
-- Selecting Windows SDK version 10.0.18362.0 to target Windows 10.0.18363.
-- The C compiler identification is MSVC 19.24.28314.0
-- The CXX compiler identification is MSVC 19.24.28314.0
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.24.28314/bin/Hostx64/x64/cl.exe
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.24.28314/bin/Hostx64/x64/cl.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.24.28314/bin/Hostx64/x64/cl.exe
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.24.28314/bin/Hostx64/x64/cl.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Check for working ISPC compiler: D:/tools/bin/ispc.exeD:/tools/bin/ispc.exe
-- Check for working ISPC compiler: D:/tools/bin/ispc.exeD:/tools/bin/ispc.exe -- works
-- Configuring done
-- Generating done
-- Build files have been written to: D:/cmake/ispc-language/build

```

And when building:

```
 Checking Build System
  Building Custom Rule D:/cmake/ispc-language/CMakeLists.txt
  Building Custom Rule D:/cmake/ispc-language/CMakeLists.txt
  a.cpp
  b.cpp
  Generating Code...
  libispc.vcxproj -> D:\cmake\ispc-language\build\Debug\libispc.lib
  Building Custom Rule D:/cmake/ispc-language/CMakeLists.txt

```

What am I missing ?

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [February 24, 2020, 2:14pm UTC](https://discourse.cmake.org/t/ispc-language-support/673/2 "2020-02-24T14:14:49Z")

</div>

This may require additional support from the VS generator itself. See for example the [code here](https://gitlab.kitware.com/cmake/cmake/blob/v3.16.4/Source/cmVisualStudio10TargetGenerator.cxx#L2160-2178) that maps from source file language to the corresponding `.vcxproj` tool.

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [February 24, 2020, 2:15pm UTC](https://discourse.cmake.org/t/ispc-language-support/673/3 "2020-02-24T14:15:38Z")

</div>

Alternatively you can try focusing on getting it to work with the `NMake Makefiles` or `Ninja` generators at a command prompt with the appropriate environment loaded.

---

<div class="post-metadata">

### Author: ![Lectem](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lectem/32/380_2.png) [@Lectem](https://discourse.cmake.org/u/Lectem)
#### Post date: [February 25, 2020, 9:22am UTC](https://discourse.cmake.org/t/ispc-language-support/673/4 "2020-02-25T09:22:35Z")

</div>

Thanks I will take a look.  
Is the VS generator only using prebuilt msbuild targets ?  
I suppose I might have to create my own targets for the VS generator if I need to support it.  
I’ll try with Ninja too.

---

<div class="post-metadata">

### Author: ![Lectem](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lectem/32/380_2.png) [@Lectem](https://discourse.cmake.org/u/Lectem)
#### Post date: [February 25, 2020, 10:06am UTC](https://discourse.cmake.org/t/ispc-language-support/673/5 "2020-02-25T10:06:42Z")

</div>

So small update on linux with Ninja:

I got the following message

> CMake Error: Error required internal CMake variable not set, cmake may not be built correctly.  
> Missing variable is:  
> CMAKE\_ISPC\_LINK\_EXECUTABLE

The thing is, ISPC relies on the C linker as it can only generate object files.  
I saw that some languages define `CMAKE_<LANG>_LINK_EXECUTABLE` to `<LANG>_NO_LINK_EXECUTABLE` (such as CSharp) but I am not sure it is the right thing to do. (Mainly because then we can’t do a try\_compile).

I thought it would be the same for ASM but it actually uses the same executable both for compiling and linking.  
Is there a way to tell CMake that ISPC needs to use C/CXX or any other linker based on what the user asks ?

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [February 25, 2020, 12:13pm UTC](https://discourse.cmake.org/t/ispc-language-support/673/6 "2020-02-25T12:13:31Z")

</div>

> [@Lectem](#):
>
> Is there a way to tell CMake that ISPC needs to use C/CXX or any other linker

Something like this may work (untested):

```cmake
if(NOT CMAKE_C_COMPILER_LOADED OR NOT DEFINED CMAKE_C_LINK_EXECUTABLE)
  message(FATAL_ERROR "C must be enabled before ISPC")
endif()

set(CMAKE_ISPC_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE}")

```

---

<div class="post-metadata">

### Author: ![Lectem](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lectem/32/380_2.png) [@Lectem](https://discourse.cmake.org/u/Lectem)
#### Post date: [February 25, 2020, 1:40pm UTC](https://discourse.cmake.org/t/ispc-language-support/673/7 "2020-02-25T13:40:47Z")

</div>

It seems it could work to some extent, but I’m now encountering another issue I forgot about:  
ispc generates headers for communication with C/C++. Maybe the other option would be to keep an invalid value for the linker and add `set(CMAKE_ISPC_LINKER_PREFERENCE 0)` to enforce any other linker ?

Obvisouly, it means there is a dependency between a C or C++ file using an ISPC function.  
I’m not sure anymore if adding ISPC as language in CMake is a good idea (even though it is a language) or if we should go the custom target route.

I don’t think CMake supports dependencies for source files inside a target itself ? That would probably mean users need to always put their ISPC source in an individual target (might be the logical thing to do though ?).

Right now I’m bypassing the `try_compile` call for testing purposes (otherwise it tries to compile the .cpp file before the .ispc one, and won’t find the header).

So the questions I think need answers are:

- Should ISPC be supported as a language or a module that creates custom targets ?
- Can CMake understand somehow that a language can generate both object and headers ? Or maybe it doesn’t need to know ? It at least needs to know about the compilation order and the additional include folder. (We could document ISPC targets shouldn’t be mixed with other languages directly)
- Should headers generated by ISPC be considered PRIVATE or PUBLIC (I think private but I’m not 100% sure)

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [February 26, 2020, 12:01pm UTC](https://discourse.cmake.org/t/ispc-language-support/673/8 "2020-02-26T12:01:16Z")

</div>

This is touching on the general idea of domain-specific languages that produce C sources or headers. Lexer and parser generators like flex and bison are other examples. We do not currently have a first-class way to model that, so we typically go with the `add_custom_command`/`add_custom_target` approach.

I suggest using the custom command/target approach for ISPC for now. The custom commands can even be part of regular C or C++ targets because we already support generated header files in custom commands where the headers are then used to compile the C or C++ sources.

The headers generated by ISPC do not need to be explicitly considered private or public and do not need to be implicitly added to the `PUBLIC_HEADER` or `PRIVATE_HEADER` target properties at all. We don’t do that for normal C headers either. Projects can specify those explicitly or handle installation themselves via `install(FILES)`.

---

<div class="post-metadata">

### Author: ![Lectem](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lectem/32/380_2.png) [@Lectem](https://discourse.cmake.org/u/Lectem)
#### Post date: [March 3, 2020, 2:16pm UTC](https://discourse.cmake.org/t/ispc-language-support/673/9 "2020-03-03T14:16:15Z")

</div>

So I’m making progress by using `target_sources` + `add_custom_command` but I’m hitting another issue: architecture detection.  
I found a few issues related to `CMAKE_<LANG>_COMPILER_ARCHITECTURE_ID` such as [https://gitlab.kitware.com/cmake/cmake/issues/17702](https://gitlab.kitware.com/cmake/cmake/issues/17702) and the documentation states that it is “An internal variable subject to change.”.

Right now the scripts for ispc examples ([https://github.com/ispc/ispc/blob/master/examples/cmake/AddISPCExample.cmake#L47](https://github.com/ispc/ispc/blob/master/examples/cmake/AddISPCExample.cmake#L47)) uses uname to determine the architecture. I do not really like this since it makes it harder to support cross compilation.

I found that android and osx have their own `CMAKE_ANDROID_ARCH_ABI` and `CMAKE_OSX_ARCHITECTURES`.

Since I would like for ISPC support to be upstreamed at some point, what should I be using ?  
Should I populate `CMAKE_ISPC_COMPILER_ARCHITECTURE_ID` based on the languages of the current project (most likely `CMAKE_C_COMPILER_ARCHITECTURE_ID` or `CMAKE_CXX_COMPILER_ARCHITECTURE_ID` ? I saw from the issue that one was not supposed to set those variables from the cache, should I provide another variable in case detection fails ?

If possible I’d like to deduce the target architecture correctly when someone uses a toolchain file, but from what I understand I might need to detect it from various variables depending on the toolchain ?

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [March 3, 2020, 2:35pm UTC](https://discourse.cmake.org/t/ispc-language-support/673/10 "2020-03-03T14:35:37Z")

</div>

`CMAKE_<LANG>_COMPILER_ARCHITECTURE_ID` is meant for use by code within CMake that needs to know the architecture. It can be used for supporting custom languages externally, but with the caveat about support mentioned in [https://gitlab.kitware.com/cmake/cmake/-/blob/v3.16.4/Modules/CMakeAddNewLanguage.txt](https://gitlab.kitware.com/cmake/cmake/-/blob/v3.16.4/Modules/CMakeAddNewLanguage.txt). Of course if ISPC support were upstreamed that wouldn’t be a concern.

---

<div class="post-metadata">

### Author: ![Lectem](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lectem/32/380_2.png) [@Lectem](https://discourse.cmake.org/u/Lectem)
#### Post date: [March 5, 2020, 10:13am UTC](https://discourse.cmake.org/t/ispc-language-support/673/11 "2020-03-05T10:13:29Z")

</div>

I now have a decent function that compiles things correctly but I wanted to support CMAKE\_ISPC\_FLAGS\_ to some extent. I’d need to be able to choose the right variable at generation time.

I however didn’t find a good way to do it using genexpressions. (since variables would be expanded at configuration time).  
The “trick” I thought about was to use file properties but gen expressions can only retrieve target properties. I could put the properties in the target but there might be a better way?

To be clear I’m trying to do the equivalent of `${CMAKE_ISPC_FLAGS_$<CONFIG>}` in my `add_custom_command` COMMAND

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [March 5, 2020, 12:00pm UTC](https://discourse.cmake.org/t/ispc-language-support/673/12 "2020-03-05T12:00:53Z")

</div>

`CMAKE_<LANG>_FLAGS_<CONFIG>` is normally handled by the generators, so that won’t be a problem if the language were converted to first-class.

For `add_custom_command` something like this may work:

```cmake
add_custom_command(...
   COMMAND ... "$<$<CONFIG:Debug>:${CMAKE_ISPC_FLAGS_DEBUG}>"
               "$<$<CONFIG:Release>:${CMAKE_ISPC_FLAGS_RELEASE}>"
               ...
   COMMAND_EXPAND_LISTS
  ...)

```

_except_ that the flag variables normally hold command-line strings with whitespace-separated, possibly quoted arguments. You’d have to separate those first into other variables and then reference those others in the generator expressions.

---

<div class="post-metadata">

### Author: ![Lectem](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lectem/32/380_2.png) [@Lectem](https://discourse.cmake.org/u/Lectem)
#### Post date: [March 5, 2020, 12:08pm UTC](https://discourse.cmake.org/t/ispc-language-support/673/13 "2020-03-05T12:08:31Z")

</div>

It seems to work, I ended up using logic similar to the `cmake_initialize_per_config_variable` (from `Modules\CMakeInitializeConfigs.cmake`) to concatenate genexpressions for all build types of interest. I indeed needed the `COMMAND_EXPAND_LISTS` so that `add_custom_command` would not put quotes around the flags.

---

<div class="post-metadata">

### Author: ![Lectem](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lectem/32/380_2.png) [@Lectem](https://discourse.cmake.org/u/Lectem)
#### Post date: [March 23, 2020, 6:17pm UTC](https://discourse.cmake.org/t/ispc-language-support/673/14 "2020-03-23T18:17:19Z")

</div>

So I made great progress with a `FindISPC.cmake` file but I still have a few issues.  
One of them is that on my linux distribution (linux mint 19.3, based on ubuntu 18.04LTS), it seems that gcc defaults to using PIE.

This leads to issues because by default I chosed not to emit `--pic` for ISPC commands, respecting the `POSITION_INDEPENDENT_CODE` property of my targets.  
Is there a way to check if the compiler requires `--pic` or not ? I know there is [CheckPIESupported](https://cmake.org/cmake/help/latest/module/CheckPIESupported.html) but it only checks if it is supported, not if it is actually enabled by default.

Should I actually use `-fPIC` if `POSITION_INDEPENDENT_CODE` is not set ? I’m a bit worried about the potential performance impact. Ideally if something could tell me if PIC/PIE is enabled by default by the linker it would be great.

---

<div class="post-metadata">

### Author: ![marc.chevrier](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/ecb155/32.png) [@marc.chevrier](https://discourse.cmake.org/u/marc.chevrier)
#### Post date: [March 24, 2020, 10:24am UTC](https://discourse.cmake.org/t/ispc-language-support/673/15 "2020-03-24T10:24:52Z")

</div>

There is no way to check if compiler option for `PIC` is supported or what is the default behavior (i.e. `PIC` or no `PIC`).

`CMake` will generate `PIC` option only if property `POSITION_INDEPENDENT_CODE` is `TRUE`. So I strongly recommend to not set any `PIC` compiler option by default.

For `PIE`, you can specify both options (if your compiler support them), through variables `CMAKE_<LANG>_LINK_OPTIONS_PIE` and `CMAKE_<LANG>_LINK_OPTIONS_NO_PIE`, for activating or deactivating `PIE` generation. The `CMake` generation rule is the following, depending on target property value:

- `POSITION_INDEPENDENT_CODE` not set, no `PIE` flags generated.
- `POSITION_INDEPENDENT_CODE` is set to `TRUE`, variable `...PIE` is used.
- `POSITION_INDEPENDENT_CODE` is set to `FALSE`, variable `...NO_PIE` is used.

So to sum up: without any `POSITION_INDEPENDENT_CODE` target property, use defaults compiler/linker behavior.  
Set the property (`TRUE` or `FALSE`) only when you want a specific behavior. `PIE` or not `PIE` executable.

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [March 24, 2020, 1:56pm UTC](https://discourse.cmake.org/t/ispc-language-support/673/16 "2020-03-24T13:56:24Z")

</div>

IIUC the problem is that the ISPC toolchain and the GNU toolchain on a given system do not necessarily agree about the default w.r.t. PIC. If no flags are used at all the resulting binary may not link correctly. For ISPC we need to know whether the C/C++ compiler enables PIC/PIE by default in order to match it via explicit flags. Therefore we need a way to detect, perhaps via `try_compile`, what the C compile does.

---

<div class="post-metadata">

### Author: ![Lectem](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lectem/32/380_2.png) [@Lectem](https://discourse.cmake.org/u/Lectem)
#### Post date: [March 24, 2020, 2:18pm UTC](https://discourse.cmake.org/t/ispc-language-support/673/17 "2020-03-24T14:18:21Z")

</div>

I gave [CheckSymbolExists](https://cmake.org/cmake/help/latest/module/CheckSymbolExists.html) a try, to check if ` __PIC__ ` or ` __PIE__ ` are defined. Those are indeed defined on my system by default, and are not if I use -fno-pic (though the program won’t compile since the linker still tries to generate a PIE).

This seems like a decent thing to do when GCC or clang is detected, but I’m not sure if it’s the right way to do this? Could other compilers show the same issue ? I think it is more a linker issue than compiler, but I’m not sure how one could check the linker defaults except by using ` try_compile` with `-fno-pic`.  
I doubt the compiler would be configured without pic/pie if the linker defaults to pie, but I’m not an expert in the domain.

---

<div class="post-metadata">

### Author: ![marc.chevrier](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/ecb155/32.png) [@marc.chevrier](https://discourse.cmake.org/u/marc.chevrier)
#### Post date: [March 24, 2020, 2:34pm UTC](https://discourse.cmake.org/t/ispc-language-support/673/18 "2020-03-24T14:34:37Z")

</div>

FYI, `PIE` and `PIC` are partly uncorrelated:

- You can generate an executable with option `-fpie` or option `-fno-pie` with files compiled in `PIC` mode.
- To generate an executable with option `-fpie`, it is **required** to compile in PIC mode.

So, for your compiler, I think defining variables `CMAKE_<LANG>_COMPILE_OPTIONS_PIC`, `CMAKE_<LANG>_LINK_OPTIONS_PIE` and `CMAKE_<LANG>_LINK_OPTIONS_NO_PIE` will be enough. And manage `PIE` link step by using [CheckPIESupported](https://cmake.org/cmake/help/latest/module/CheckPIESupported.html#module:CheckPIESupported) module.

---

<div class="post-metadata">

### Author: ![Lectem](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lectem/32/380_2.png) [@Lectem](https://discourse.cmake.org/u/Lectem)
#### Post date: [March 24, 2020, 2:56pm UTC](https://discourse.cmake.org/t/ispc-language-support/673/19 "2020-03-24T14:56:13Z")

</div>

> So, for your compiler, I think defining variables CMAKE\ __COMPILE\_OPTIONS\_PIC, CMAKE__ LINK\_OPTIONS\_PIE and CMAKE_\_LINK\_OPTIONS\_NO\_PIE will be enough.

Not really, it is kind of the behaviour I have right now. As @brad.king mentioned, the issue is that the linker coming with my linux distribution defaults to using PIE (and GCC compiles with PIC/PIE by default too) without us having to give it any flag.  
ISPC, which produces object files, has a different default which is not to enable PIC.

So right now, everything compiles, but when I try to link I’m getting an error because the linker expects both GCC and ISPC to produce objects that have position independent code.

So right now, by default (regardless of `CMAKE_<LANG>_LINK_OPTIONS_PIE` / `CMAKE_<LANG>_LINK_OPTIONS_NO_PIE`) it will not build correctly on this system, due to GNU tools and ISPC having different defaults.  
That’s what I’m trying to fix.

If `CMAKE_<lang>_LINK_OPTIONS_NO_PIE` is used by default (when `CMAKE_POSITION_INDEPENDENT_CODE` is not set) then what I would need is for `CMAKE_C_LINK_OPTIONS_NO_PIE` and `CMAKE_CXX_LINK_OPTIONS_NO_PIE` to actually use the flag `-fno-pie` for GCC/clang instead of nothing?

EDIT:

Basicly, the following (pseudocode) won’t work.

```auto
$CC main.c -o main.o
ispc code.ispc -o code.o
$LD main.o code.o 

```

and ouput something along the lines of

```auto
/usr/bin/ld: (code.o): relocation R_X86_64_32S against `.rodata' can not be used when making a PIE object; recompile with -fPIC

```

---

<div class="post-metadata">

### Author: ![marc.chevrier](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/ecb155/32.png) [@marc.chevrier](https://discourse.cmake.org/u/marc.chevrier)
#### Post date: [March 24, 2020, 3:18pm UTC](https://discourse.cmake.org/t/ispc-language-support/673/20 "2020-03-24T15:18:29Z")

</div>

No. `CMAKE_<lang>_LINK_OPTIONS_NO_PIE` is not used by default. If `POSITION_INDEPENDENT_CODE` is not set (`TRUE` or `FALSE`), no flags are applied to link step.

`PIE` flag (`-fpie` or `-fno_pie`) is applied **only** if property `POSITION_INDEPENDENT_CODE` is set (‘TRUE’ or ‘FALSE’).

To ensure consistency for the link step, define the variable `CMAKE_POSITION_INDEPENDENT_CODE` and include module `CheckPIESupport` in the root `CMakelist.txt` and call `check_pie_supported()`.

variable `CMAKE_POSITION_INDEPENDENT_CODE` can take `TRUE` or `FALSE`:

- set to `FALSE`: `gcc` and `ispc` will compile in their default mode (`PIC` for gcc and `NO_PIC` for ispc) but the linker will specify `-fno_pie` so link will succeed.
- set to `TRUE`: `gcc` and `ispc` will compile with option `-fPIC` and the linker will use option `-fpie` and the link will succeed.

[Next page](https://discourse.cmake.org/t/ispc-language-support/673.md?page=2)
