Modular programs are built as a combination of separate modules, which may be developed and verified separately. Therefore, in order to reason over such programs, compositionality plays a crucial role: the semantics of the whole program must be obtainable as a simple function from the semantics of its individual modules. In the field of logic programming, the need for a compositional semantics has been long recognized, however, while for definite (i.e. negationfree) logic programs a few such semantics have been proposed, in the literature of normal logic programs (programs which employ the negation operator), compositionality has received scarce attention. This is mainly due to the fact that normal programs typically have a nonmonotonic behavior, which is difficult to fit in a compositional framework. Here we propose a declarative compositional semantics for general logic programs. First, a compositional semantics for first-order modules is presented and proved correct wrt the set of logical consequences of the module in three-valued logic. In a second stage, the obtained results are applied to modular normal logic programs, obtaining a semantics which is correct with respect to the set of logical consequences of the completion of the program and — in contrast with the other approaches — which is always computable. This semantics might be regarded as a compositional counterpart of Kunen's semantics. Finally we discuss and show how these results have to be modified in order to be applied to normal constraint logic programs.